<template>
  <div class="stock-container">
    <SearchForm
      :formItem="formItem"
      :addFlag="true"
      class="search-form"
      @add="addFun"
      @search="handleSearch"
      @reset="reset"
    >
      <template #btn>
        <el-button :icon="Download" type="primary" plain @click="download">导出</el-button>
        <el-button :icon="Upload" type="primary" plain @click="handleImportClick">导入</el-button>
        <!-- 新增文件选择器（隐藏） -->
        <input
          ref="fileInput"
          type="file"
          accept=".json"
          style="display: none; width: 0px; height: 0px"
          @change="handleFileSelected"
        />
      </template>
    </SearchForm>

    <div class="total-row">
      <div class="total">
        <!-- 今日盈亏 -->
        <div class="stat-item" :class="computedTotalData[0].value >= 0 ? 'profit' : 'loss'">
          <div class="stat-content">
            <div class="stat-label-container">
              <span class="stat-label">{{ computedTotalData[0].label }}:</span>
              <span class="stat-change" :class="todayProfitPercent >= 0 ? 'profit' : 'loss'">
                {{ todayProfitPercent >= 0 ? '+' : '' }}{{ todayProfitPercent.toFixed(2) }}%
              </span>
            </div>
            <span class="stat-value">
              {{ computedTotalData[0].value >= 0 ? '+' : '' }}
              {{ computedTotalData[0].value.toFixed(2) }}
              <span class="stat-unit">元</span>
            </span>
          </div>
        </div>

        <!-- 持仓盈亏 -->
        <div class="stat-item" :class="computedTotalData[1].value >= 0 ? 'profit' : 'loss'">
          <div class="stat-content">
            <div class="stat-label-container">
              <span class="stat-label">{{ computedTotalData[1].label }}:</span>
              <span
                class="stat-change"
                :class="holdingAmountChangePercent >= 0 ? 'profit' : 'loss'"
              >
                {{ holdingAmountChangePercent >= 0 ? '+' : ''
                }}{{ holdingAmountChangePercent.toFixed(2) }}%
              </span>
            </div>

            <span class="stat-value">
              {{ computedTotalData[1].value >= 0 ? '+' : '' }}
              {{ computedTotalData[1].value.toFixed(2) }}
              <span class="stat-unit">元</span>
            </span>
          </div>
        </div>

        <!-- 总持仓金额 -->
        <div class="stat-item">
          <div class="stat-content">
            <span class="stat-label">{{ computedTotalData[2].label }}:</span>
            <span class="stat-value">
              {{ computedTotalData[2].value.toFixed(2) }}
              <span class="stat-unit">元</span>
            </span>
          </div>
        </div>

        <!-- 总投入成本 -->
        <div class="stat-item">
          <div class="stat-content">
            <span class="stat-label">{{ computedTotalData[3].label }}:</span>
            <span class="stat-value">
              {{ computedTotalData[3].value.toFixed(2) }}
              <span class="stat-unit">元</span>
            </span>
          </div>
        </div>
      </div>
    </div>
    <BasicTable
      :columns="columns"
      :tableData="tableData"
      :pageConfig="false"
      class="basic-table"
      :operation-flag="true"
      :operation-width="120"
      :operationFixed="true"
      @delete-fun="deleteFun"
      @edit-fun="editFun"
    >
    </BasicTable>
    <BasicDialog
      width="60%"
      :dialogVisible="dialogVisible"
      :dialog-data="dialogData"
      :title="dialogTitle"
      :dialogForm="dialogForm"
      :rules="dialogRules"
      labelWidth="140px"
      :span="12"
      @saveAndUpdate="saveAndUpdate"
      @closed="dialogVisible = false"
    >
    </BasicDialog>
  </div>
</template>

<script setup lang="ts">
import SearchForm, { type FormItem } from '@/components/Search/Index.vue'
import BasicTable, { type Column } from '@/components/Table/Index.vue'
import BasicDialog, { type FormFieldType } from '@/components/Dialog/Index.vue'
import { useProfitStore } from '@/stores/profitStore'
import type { FormRules } from 'element-plus'
import { onMounted, ref, h, type Ref, nextTick, computed, onUnmounted } from 'vue'
import { ElMessage, ElLoading } from 'element-plus'
// import { queryStockDetailsApi } from '@/api/modules/Rich'
import { Download, Upload } from '@element-plus/icons-vue'

// 导入InvestmentDB服务
import {
  getAllStocks,
  getStockByCode,
  addStock,
  updateStock,
  deleteStock,
  type StockItem,
} from '@/data/InvestmentDB'
import {
  exportInvestmentDB,
  importInvestmentDB,
  downloadJSON,
  readJSONFile,
} from '@/data/indexedDBExporter'
// 从store获取股票盈亏数据
const profitStore = useProfitStore()
const computedTotalData = computed(() => {
  return [
    { label: '今日盈亏', value: profitStore.stockProfit.todayProfit },
    { label: '持仓盈亏', value: profitStore.stockProfit.holdingProfit },
    { label: '总持仓金额', value: profitStore.stockProfit.totalHoldingAmount },
    { label: '总投入成本', value: profitStore.stockProfit.totalInvestmentAmount },
  ]
})

// 计算总持仓金额相较于成本的百分比变化
const holdingAmountChangePercent = computed(() => {
  const cost = computedTotalData.value[3].value
  if (cost === 0) return 0
  return ((computedTotalData.value[2].value - cost) / cost) * 100
})

// 计算今日盈亏相较于总持仓金额的百分比变化
const todayProfitPercent = computed(() => {
  const totalAmount = computedTotalData.value[2].value
  if (totalAmount === 0) return 0
  return (computedTotalData.value[0].value / totalAmount) * 100
})
// 搜索相关数据
const searchData: Ref<{ code: string }> = ref({
  code: '',
})

// 搜索表单配置
const formItem: FormItem[] = [
  {
    name: 'code',
    label: '代码',
    type: 'input',
  },
]

const columns: Column[] = [
  { label: '股票代码', prop: 'code', width: 120 },
  { label: '股票名称', prop: 'name', align: 'left', width: 180 },
  {
    label: '今日盈亏',
    prop: 'todayProfit',
    width: 120,
    sortable: true,
    sortMethod: (a: StockItem, b: StockItem) => {
      // 兼容number和string类型的排序
      const valueA =
        typeof a.todayProfit === 'number' ? a.todayProfit : parseFloat(a.todayProfit || '0')
      const valueB =
        typeof b.todayProfit === 'number' ? b.todayProfit : parseFloat(b.todayProfit || '0')
      return valueA - valueB
    },
    formatter: (row: StockItem) => {
      // 兼容number和string类型，统一转为数字处理
      const todayProfit =
        typeof row.todayProfit === 'number' ? row.todayProfit : Number(row.todayProfit || 0)

      const formatted = todayProfit.toFixed(2) // 强制保留两位小数
      return h(
        'span',
        {
          class:
            todayProfit > 0
              ? 'text-red-500 font-medium'
              : todayProfit < 0
                ? 'text-green-500 font-medium'
                : '',
        },
        todayProfit >= 0 ? `+${formatted}` : formatted,
      )
    },
  },

  {
    label: '涨跌幅',
    prop: 'change',
    width: 100,
    sortable: true,
    sortMethod: (a: StockItem, b: StockItem) => {
      const valueA = typeof a.change === 'number' ? a.change : parseFloat(a.change || '0')
      const valueB = typeof b.change === 'number' ? b.change : parseFloat(b.change || '0')
      return valueA - valueB
    },
    formatter: (row: StockItem) => {
      const change = typeof row.change === 'number' ? row.change : Number(row.change || 0)
      return h(
        'span',
        {
          class: change > 0 ? 'text-red-500' : change < 0 ? 'text-green-500' : '',
        },
        `${change.toFixed(2)}%`,
      )
    },
  },

  {
    label: '投入金额',
    prop: 'investment',
    width: 120,
    sortable: true,
    sortMethod: (a: StockItem, b: StockItem) => {
      const valueA =
        typeof a.investment === 'number' ? a.investment : parseFloat(a.investment || '0')
      const valueB =
        typeof b.investment === 'number' ? b.investment : parseFloat(b.investment || '0')
      return valueA - valueB
    },
    formatter: (row: StockItem) => {
      const investment =
        typeof row.investment === 'number' ? row.investment : Number(row.investment || 0)
      return h('span', investment.toFixed(2))
    },
  },
  {
    label: '持仓金额',
    prop: 'holdingValue',
    width: 120,
    sortable: true,
    sortMethod: (a: StockItem, b: StockItem) => {
      const valueA =
        typeof a.holdingValue === 'number' ? a.holdingValue : parseFloat(a.holdingValue || '0')
      const valueB =
        typeof b.holdingValue === 'number' ? b.holdingValue : parseFloat(b.holdingValue || '0')
      return valueA - valueB
    },
    formatter: (row: StockItem) => {
      const holdingValue =
        typeof row.holdingValue === 'number' ? row.holdingValue : Number(row.holdingValue || 0)
      return h('span', holdingValue.toFixed(2))
    },
  },
  {
    label: '持仓盈亏',
    prop: 'profit',
    width: 120,
    sortable: true,
    sortMethod: (a: StockItem, b: StockItem) => {
      const valueA = typeof a.profit === 'number' ? a.profit : parseFloat(a.profit || '0')
      const valueB = typeof b.profit === 'number' ? b.profit : parseFloat(b.profit || '0')
      return valueA - valueB
    },
    formatter: (row: StockItem) => {
      const profit = typeof row.profit === 'number' ? row.profit : Number(row.profit || 0)

      const formatted = profit.toFixed(2)
      return h(
        'span',
        {
          class:
            profit > 0
              ? 'text-red-500 font-medium'
              : profit < 0
                ? 'text-green-500 font-medium'
                : '',
        },
        profit >= 0 ? `+${formatted}` : formatted,
      )
    },
  },
  {
    label: '持仓盈亏率',
    prop: 'profitRate',
    width: 120,
    sortable: true,
    sortMethod: (a: StockItem, b: StockItem) => {
      const valueA =
        typeof a.profitRate === 'number' ? a.profitRate : parseFloat(a.profitRate || '0')
      const valueB =
        typeof b.profitRate === 'number' ? b.profitRate : parseFloat(b.profitRate || '0')
      return valueA - valueB
    },
    formatter: (row: StockItem) => {
      const profitRate =
        typeof row.profitRate === 'number' ? row.profitRate : Number(row.profitRate || 0)

      const formatted = profitRate.toFixed(2)
      return h(
        'span',
        {
          class:
            profitRate > 0
              ? 'text-red-500 font-medium'
              : profitRate < 0
                ? 'text-green-500 font-medium'
                : '',
        },
        profitRate >= 0 ? `+${formatted}%` : `${formatted}%`,
      )
    },
  },
  { label: '最新价格', prop: 'price', width: 100 },
  { label: '昨收', prop: 'preClose', width: 100 },
  { label: '单位成本', prop: 'cost', width: 100 },
  { label: '持仓数', prop: 'holdings' },
  {
    label: '类型',
    prop: 'type',
    width: 100,
    sortable: true,
    formatter: (row: StockItem) => {
      const typeMap = {
        stock: '股票',
        fund: '场内基金',
        convertible: '可转债',
      }
      return typeMap[row.type as keyof typeof typeMap] || '未知'
    },
  },
]

// 表格数据
const tableData = ref<StockItem[]>([])
// 原始数据备份，用于重置搜索
const originalTableData = ref<StockItem[]>([])

// 对话框相关状态
const dialogVisible = ref(false)
const dialogTitle = ref('新增股票')
const dialogData = ref<Partial<StockItem>>({})
const dialogLoading = ref(false)

// 对话框表单配置
const dialogForm: Array<FormFieldType> = [
  {
    label: '股票代码',
    value: 'code',
    type: 'input',
    placeholder: '请输入股票代码',
    disabled: computed(() => dialogTitle.value !== '新增股票'),
  },
  {
    label: '成本',
    value: 'cost',
    type: 'input',
    placeholder: '请输入成本',
  },
  {
    label: '持仓数量',
    value: 'holdings',
    type: 'input',
  },
  {
    label: '税费',
    value: 'tax',
    type: 'input',
  },
  {
    label: '产品类型',
    value: 'type',
    type: 'select',
    optionConfig: {
      options: [
        { label: '股票', value: 'stock' },
        { label: '场内基金', value: 'fund' },
        { label: '可转债', value: 'convertible' },
      ],
    },
    placeholder: '请选择产品类型',
  },
]

// 检查股票代码唯一性（从IndexedDB检查）
const checkCodeUnique = (rule: any, value: string, callback: any) => {
  if (!value) return callback()

  // 编辑状态且代码未改变时不验证唯一性
  if (dialogTitle.value === '修改股票' && dialogData.value.code === value) {
    return callback()
  }

  getStockByCode(value)
    .then((stock) => {
      if (stock) {
        callback(new Error('该股票代码已存在'))
      } else {
        callback()
      }
    })
    .catch((error) => {
      console.error('检查股票代码唯一性失败:', error)
      callback(new Error('检查股票代码失败，请重试'))
    })
}

// 对话框表单验证规则
const dialogRules: FormRules = {
  code: [
    { required: true, message: '请输入股票代码', trigger: 'blur' },
    { validator: checkCodeUnique, trigger: 'blur' },
  ],
  // 新增类型验证
  type: [{ required: true, message: '请选择产品类型', trigger: 'change' }],
}

// 刷新表格数据
const refreshTableData = async () => {
  try {
    const data = await getAllStocks()
    tableData.value = data
    originalTableData.value = [...data]
  } catch (error) {
    console.error('刷新股票数据失败:', error)
    ElMessage.error('加载股票数据失败，请重试')
  } finally {
    // loading.close()
  }
}

// 打开对话框
const openDialog = (data: Partial<StockItem> = {}) => {
  dialogData.value = { ...data }
  dialogTitle.value = data.code ? '修改股票' : '新增股票'
  dialogVisible.value = true

  // 重置对话框加载状态
  nextTick(() => {
    dialogLoading.value = false
  })
}

// 新增按钮点击
const addFun = () => {
  openDialog({})
}

// 编辑按钮点击
const editFun = (row: StockItem) => {
  openDialog(row)
}

// 删除按钮点击
const deleteFun = async (row: StockItem) => {
  try {
    await deleteStock(row.code)
    ElMessage.success('删除成功')
    // 重新加载数据
    await refreshTableData()
  } catch (error) {
    console.error('删除股票失败:', error)
    ElMessage.error('删除失败，请重试')
  }
}

// 保存或更新数据
const saveAndUpdate = async (formData: StockItem) => {
  try {
    dialogLoading.value = true

    // 转换数值类型
    formData.price = Number(formData.price)
    formData.change = Number(formData.change)

    if (dialogTitle.value === '新增股票') {
      // 新增操作
      await addStock(formData)
      ElMessage.success('新增股票成功')
    } else {
      // 更新操作
      await updateStock(formData)
      ElMessage.success('更新股票成功')
    }

    dialogVisible.value = false
    // 重新加载数据
    await refreshTableData()
  } catch (error) {
    console.error('操作失败:', error)
    ElMessage.error('操作失败，请重试')
  } finally {
    dialogLoading.value = false
  }
}

// 搜索处理
const handleSearch = (params: any) => {
  if (params.code) {
    const searchCode = params.code.toLowerCase()
    tableData.value = originalTableData.value.filter(
      (item) =>
        item.code.toLowerCase().includes(searchCode) ||
        (item.name && item.name.toLowerCase().includes(searchCode)),
    )
  } else {
    // 重置为原始数据
    tableData.value = [...originalTableData.value]
  }
}

const reset = (data: any) => {
  searchData.value = data
  refreshTableData()
}

const download = () => {
  exportInvestmentDB('stocks')
    .then((data) => {
      console.log('导出的数据:', data)
      downloadJSON(data, 'InvestmentDB_stocks.json')
    })
    .catch((error) => console.error('导出失败:', error))
}

// 新增文件输入框的引用
const fileInput = ref<HTMLInputElement | null>(null)

// 点击导入按钮时触发文件选择
const handleImportClick = () => {
  if (fileInput.value) {
    // 重置文件输入框，确保change事件能正常触发
    fileInput.value.value = ''
    fileInput.value.click()
  }
}

// 处理选择的文件
const handleFileSelected = async (event: Event) => {
  const input = event.target as HTMLInputElement
  const file = input.files?.[0]

  if (!file) {
    return
  }

  // 验证文件类型
  if (!file.name.endsWith('.json')) {
    ElMessage.error('请选择JSON格式的文件')
    return
  }

  const loading = ElLoading.service({
    lock: true,
    text: '正在导入数据...',
    background: 'rgba(0, 0, 0, 0.7)',
  })

  try {
    // 读取文件内容
    const data = await readJSONFile(file)

    // 验证导入数据的结构
    if (!validateImportData(data)) {
      ElMessage.error('导入文件格式不正确')
      return
    }

    // 导入数据到InvestmentDB
    await importInvestmentDB('stocks', data)

    // 导入成功后刷新表格数据
    await refreshTableData()

    ElMessage.success('数据导入成功')
  } catch (error) {
    console.error('导入失败:', error)
    ElMessage.error(`导入失败: ${error instanceof Error ? error.message : '未知错误'}`)
  } finally {
    loading.close()
    // 清空文件选择
    if (input) {
      input.value = ''
    }
  }
}

// 验证导入数据的结构是否正确
const validateImportData = (data: any): boolean => {
  if (typeof data !== 'object' || data === null) {
    return false
  }

  // 检查是否包含股票存储的结构
  const storeNames = Object.keys(data)
  if (storeNames.length === 0) {
    return false
  }

  // 检查至少有一个存储包含有效的股票数据结构
  return storeNames.some((storeName) => {
    const items = data[storeName]
    if (!Array.isArray(items)) {
      return false
    }

    // 检查数组中的项目是否包含股票的基本字段
    return (
      items.length === 0 ||
      items.every(
        (item) =>
          typeof item === 'object' &&
          item !== null &&
          'key' in item &&
          'value' in item &&
          typeof item.value === 'object' &&
          item.value !== null &&
          'code' in item.value, // 股票代码是必须的字段
      )
    )
  })
}

// 用 number 类型存储定时器ID（避免使用 NodeJS.Timeout）
let refreshTimer: number | null = null

// 页面挂载时初始化数据
onMounted(async () => {
  try {
    // 加载股票数据
    await refreshTableData()
  } catch (error) {
    console.error('初始化数据失败:', error)
    ElMessage.error('初始化数据失败，请刷新页面重试')
  }
  // 设置定时器，每10秒执行一次
  // 显式指定返回值为 number 类型
  refreshTimer = window.setInterval(() => {
    refreshTableData().catch((error) => {
      console.error('定时刷新股票数据失败:', error)
    })
  }, 5000) // 10秒
})

// 组件卸载时清除定时器
onUnmounted(() => {
  if (refreshTimer !== null) {
    window.clearInterval(refreshTimer)
    refreshTimer = null
  }
})
</script>

<style lang="scss" scoped>
.stock-container {
  width: 100%;
  height: 100%;
  padding: 16px;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 65px 86px 1fr;
  grid-column-gap: 16px;
  grid-row-gap: 16px;

  .search-form {
    grid-area: 1 / 1 / 2 / 2;
  }

  .total-row {
    grid-area: 2 / 1 / 3 / 2;
    width: 100%;
  }

  .total {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
  }

  .stat-item {
    flex: 1;
    min-width: 200px;
    padding: 8px 16px;
    border-radius: 4px;
    background-color: #ffffff;
    transition: all 0.2s ease;

    &:hover {
      transform: translateY(-2px);
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
    }
  }

  // 关键修改：使用flex布局使标签和值在同一行
  .stat-content {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }

  .stat-label {
    font-size: 16px;
    color: #6b7280;
    font-weight: 500;
    white-space: nowrap; // 防止标签换行
  }

  .stat-value {
    font-size: 24px;
    font-weight: 600;
    text-align: right;
  }

  .stat-unit {
    font-size: 14px;
    margin-left: 2px;
    opacity: 0.8;
  }

  .stat-label-container {
    display: flex;
    justify-content: space-between;
  }

  .stat-change {
    font-size: 16px;
    font-weight: 500;
    padding: 2px 8px;
    border-radius: 12px;
    display: inline-block;
  }

  .stat-change.profit {
    color: #f56c6c;
    background-color: rgba(245, 108, 108, 0.1);
  }

  .stat-change.loss {
    color: #67c23a;
    background-color: rgba(103, 194, 58, 0.1);
  }

  // 盈利/亏损状态样式
  .profit {
    .stat-value {
      color: #f56c6c; // 红色表示盈利
    }
    border-left: 3px solid #f56c6c;
  }

  .loss {
    .stat-value {
      color: #67c23a; // 绿色表示亏损
    }
    border-left: 3px solid #67c23a;
  }

  .basic-table {
    grid-area: 3 / 1 / 4 / 2;
    border-radius: 4px;
    border: 1px solid #e5e7eb;
    overflow: hidden;
  }
}

// 涨跌幅样式
:deep(.text-red-500) {
  color: #f56c6c !important;
}
:deep(.text-green-500) {
  color: #67c23a !important;
}
</style>
